package service

import (
	"context"
	"database/sql"
	"github.com/jinzhu/gorm"
	"gomicrodemo/changgou-goods-service/model"
	"gomicrodemo/common/uuid"
	"time"

	"gomicrodemo/proto/goods"
	"log"
)

type DBAgent struct {
	DB *gorm.DB
}

func (o *DBAgent) GetBrand(request *goods.GetBrandsRequest) (brands []*model.Brand, err error) {
	var brand model.Brand

	db := o.DB.Model(&brand)

	if request.Limit == 0 {
		request.Limit = 10
		db = db.Limit(request.Limit)
	} else {
		db = db.Limit(request.Limit)
	}
	if request.Offset == 0 {
		request.Offset = 0
		db = db.Offset(request.Offset)
	} else {
		db = db.Offset(request.Offset)
	}
	if request.Brand != nil {
		if name := request.Brand.Name; name != "" {
			db = db.Where("name like ?", "%"+name+"%")
		}
		if id := request.Brand.Id; id != 0 {
			db = db.Where("id = ?", id)
		}
		if image := request.Brand.Image; image != "" {
			db = db.Where("image = ?", image)
		}
		if letter := request.Brand.Letter; letter != "" {
			db = db.Where("letter = ?", letter)
		}
		if seq := request.Brand.Seq; seq != 0 {
			db = db.Where("seq = ?", seq)
		}
	}
	db = db.Where("deleted_at is null")
	if err := db.Scan(&brands).Error; err != nil {
		log.Printf("GetBrand db fail, msg:%v", err)
		return nil, err
	}

	return brands, nil
}

func (o *DBAgent) GetTemplates(request *goods.GetTemplatesRequest) (templates []*model.Template, err error) {
	var template model.Template

	db := o.DB.Model(&template)

	if request.Limit == 0 {
		request.Limit = 10
		db = db.Limit(request.Limit)
	} else {
		db = db.Limit(request.Limit)
	}
	if request.Offset == 0 {
		request.Offset = 0
		db = db.Offset(request.Offset)
	} else {
		db = db.Offset(request.Offset)
	}
	if request.Template != nil {
		if name := request.Template.Name; name != "" {
			db = db.Where("name like ?", "%"+name+"%")
		}
		if id := request.Template.Id; id != 0 {
			db = db.Where("id = ?", id)
		}
		if spec_num := request.Template.SpecNum; spec_num != 0 {
			db = db.Where("spec_num = ?", spec_num)
		}
		if para_num := request.Template.ParaNum; para_num != 0 {
			db = db.Where("para_num = ?", para_num)
		}
	}
	if err := db.Scan(&templates).Error; err != nil {
		log.Printf("GetBrand db fail, msg:%v", err)
		return nil, err
	}

	return templates, nil
}

func (o *DBAgent) GetParams(request *goods.GetParamsRequest) (params []*model.Param, err error) {
	var param model.Param

	db := o.DB.Model(&param)

	if request.Limit == 0 {
		request.Limit = 10
		db = db.Limit(request.Limit)
	} else {
		db = db.Limit(request.Limit)
	}
	if request.Offset == 0 {
		request.Offset = 0
		db = db.Offset(request.Offset)
	} else {
		db = db.Offset(request.Offset)
	}
	if request.Param != nil {
		if name := request.Param.Name; name != "" {
			db = db.Where("name like ?", "%"+name+"%")
		}
		if id := request.Param.Id; id != 0 {
			db = db.Where("id = ?", id)
		}
		if options := request.Param.Options; options != "" {
			db = db.Where("options = ?", options)
		}
		if seq := request.Param.Seq; seq != 0 {
			db = db.Where("seq = ?", seq)
		}
		if template_id := request.Param.TemplateId; template_id != 0 {
			db = db.Where("template_id = ?", template_id)
		}
	}
	if err := db.Scan(&params).Error; err != nil {
		log.Printf("GetBrand db fail, msg:%v", err)
		return nil, err
	}

	return params, nil
}

func (o *DBAgent) GetSpecifications(request *goods.GetSpecificationsRequest) (specifications []*model.Specification, err error) {
	var specification model.Specification

	db := o.DB.Model(&specification)

	if request.Limit == 0 {
		request.Limit = 10
		db = db.Limit(request.Limit)
	} else {
		db = db.Limit(request.Limit)
	}
	if request.Offset == 0 {
		request.Offset = 0
		db = db.Offset(request.Offset)
	} else {
		db = db.Offset(request.Offset)
	}
	if request.Specification != nil {
		if name := request.Specification.Name; name != "" {
			db = db.Where("name like ?", "%"+name+"%")
		}
		if id := request.Specification.Id; id != 0 {
			db = db.Where("id = ?", id)
		}
		if options := request.Specification.Options; options != "" {
			db = db.Where("options = ?", options)
		}
		if seq := request.Specification.Seq; seq != 0 {
			db = db.Where("seq = ?", seq)
		}
		if template_id := request.Specification.TemplateId; template_id != 0 {
			db = db.Where("template_id = ?", template_id)
		}
	}
	if err := db.Scan(&specifications).Error; err != nil {
		log.Printf("GetBrand db fail, msg:%v", err)
		return nil, err
	}

	return specifications, nil
}

func (o *DBAgent) GetCategorys(request *goods.GetCategorysRequest) (categorys []*model.Category, err error) {
	var category model.Category

	db := o.DB.Model(&category)

	if request.Limit == 0 {
		request.Limit = 10
		db = db.Limit(request.Limit)
	} else {
		db = db.Limit(request.Limit)
	}
	if request.Offset == 0 {
		request.Offset = 0
		db = db.Offset(request.Offset)
	} else {
		db = db.Offset(request.Offset)
	}
	if request.Category != nil {
		if name := request.Category.Name; name != "" {
			db = db.Where("name like ?", "%"+name+"%")
		}
		if id := request.Category.Id; id != 0 {
			db = db.Where("id = ?", id)
		}
		if goods_num := request.Category.GoodsNum; goods_num != "" {
			db = db.Where("goods_num = ?", goods_num)
		}
		if is_show := request.Category.IsShow; is_show != 0 {
			db = db.Where("is_show = ?", is_show)
		}
		if is_menu := request.Category.IsMenu; is_menu != 0 {
			db = db.Where("is_menu = ?", is_menu)
		}
		if seq := request.Category.Seq; seq != 0 {
			db = db.Where("seq = ?", seq)
		}
		if parent_id := request.Category.ParentId; parent_id != 0 {
			db = db.Where("parent_id = ?", parent_id)
		}
		if template_id := request.Category.TemplateId; template_id != 0 {
			db = db.Where("template_id = ?", template_id)
		}
	}
	if err := db.Scan(&categorys).Error; err != nil {
		log.Printf("GetBrand db fail, msg:%v", err)
		return nil, err
	}

	return categorys, nil
}

func (o *DBAgent) CreateSpu(spu *model.Spu, skuList []*model.Sku) error {

	//插入spu
	tx := o.DB.BeginTx(context.Background(), &sql.TxOptions{})
	defer tx.Rollback()
	spu.Id = uuid.GetUUID()
	err := tx.Model(model.Spu{}).Create(spu).Error
	if err != nil {
		log.Printf("CreateSpu db fail, msg:%v", err.Error())
		return err
	}
	//插入sku
	err = o.CreateSku(tx, skuList)
	if err != nil {
		log.Printf("GetBrand db fail, msg:%v", err.Error())
		return err
	}
	//提交失败则回滚操作
	err = tx.Commit().Error
	if err != nil {
		log.Printf("GetBrand db fail, msg:%v", err.Error())
		return err
	}
	return err
}

func (o *DBAgent) CreateSku(tx *gorm.DB, skuList []*model.Sku) error {
	for _, v := range skuList {
		createTime, updateTime := convertTime(time.Now(), time.Now())
		v.CreateTime = createTime
		v.UpdateTime = updateTime
		v.Id = uuid.GetUUID()
		err := tx.Model(&model.Sku{}).Create(v).Error
		if err != nil {
			log.Printf("GetBrand db fail, msg:%v", err.Error())
			return err
			break
		}
	}
	return nil
}

func convertTime(createdat, updatedat time.Time) (time.Time, time.Time) {
	year, month, day := createdat.Date()
	createdat = time.Date(
		year, month, day, createdat.Hour(),
		createdat.Minute(), createdat.Second(),
		0, createdat.Location(),
	)

	year2, month2, day2 := updatedat.Date()
	updatedat = time.Date(
		year2, month2, day2, updatedat.Hour(),
		updatedat.Minute(), updatedat.Second(),
		0, updatedat.Location(),
	)
	return createdat, updatedat
}
